class StrNumber:
    '''
        十进制数字的标准表示方法。
        支持的标准类型包括：int、float、科学计数法
        不支持的类型有：'_'连接符、省略首位0、多个'-'。
    '''
    def __init__(self, number:str|int|float = '0'):
        self.sign = 1   # 非负性
        self.val  = (0,)# 有效数字
        self.dot  = 0   # 小数点位置，从后往前数
        self.e    = 0   # 数量级
        if isinstance(number, str):
            self.from_str(number)
        else:
            self.from_number(number)

    def from_str(self, number:str) -> None:
        ''' 从字符串转换，依次检查 e|E, ., +|-, other, 数字
            标准格式：(正负号, 小数位数, 常用对数指数, tuple(数字)) '''
        number = number.lower()
        e_count  = number.count('e')
        if e_count == 0:
            number_arr = self.float_str(number)
            if number_arr:
                self.sign = number_arr[0]
                self.val  = number_arr[2]
                self.dot  = number_arr[1]
                self.e    = 0
            else: 
                print('数字格式有误！')
                return None
        elif e_count == 1:
            num1,num2 = number.split('e')
            # e前部分，为一个float_str类型
            num1 = self.float_str(num1)
            if not num1:
                print('数字格式有误！')
                return None
            # e后部分，为一个int类型
            try:
                self.e = int(num2)
            except:
                print('科学计数法格式有误！')
                return None
            self.sign = num1[0]
            self.val  = num1[2]
            self.dot  = num1[1]
        else:
            print('不能包含多个"e"')
            return None

    def from_number(self, number:int|float) -> None:
        '''从数值转换'''
        number = str(number)
        self.from_str(number)

    def int_str(self, intstr:str) -> tuple[int]:
        ''' 分析整数字符串，依次检查 +|-, other, 数字
            标准格式：(正负号, tuple(数字)) '''
        neg_count = pos_count = 0
        number_arr = []
        i = 0
        while True:
            if ord(intstr[i]) == 45:
                neg_count += 1
                if neg_count > 1:
                    print('数字开头只能有一个负号！')
                    return False
            elif ord(intstr[i]) == 43:
                pos_count += 1
                if pos_count > 1:
                    print('数字开头只能有一个负号！')
                    return False
            elif 48<= ord(intstr[i]) <= 57:
                if len(intstr[i:]) > 1 and ord(intstr[i]) == 48:
                    print('数字开头不能有0！')
                    return False
                for s in intstr[i:]:
                    if 48<= ord(s) <= 57:
                        number_arr.append(int(s))
                    else:
                        print('数字格式有误！')
                        return False
                if len(number_arr) == 0:
                    print('包含无效数字！')
                    return False
                if neg_count:
                    return (False,tuple(number_arr))
                else:
                    return (True,tuple(number_arr))
            else:
                print('数字格式有误！')
                return False
            i += 1

    def float_str(self, floatstr:str) -> tuple[int]:
        ''' 分析小数字符串，检查 '.'
            标准格式：(正负号, 小数位数, tuple(数字)) '''
        float_count  = floatstr.count('.')
        if float_count == 0:
            number_arr = self.int_str(floatstr)
            if number_arr:
                return (number_arr[0], 0, number_arr[1])
            else: 
                return False
        elif float_count == 1:
            num1,num2 = floatstr.split('.')
            # 小数点前部分，为一个int_str类型
            num1 = self.int_str(num1)
            # 小数点后部分，为一个纯number_str类型
            if num1:
                number_arr = list(num1[1])
                dot_offset = 0
                for s in num2:
                    if 48<= ord(s) <= 57:
                        number_arr.append(int(s))
                    else:
                        print('数字格式有误！')
                        return False
                    dot_offset += 1
                return (num1[0], dot_offset, tuple(number_arr))
        else:
            print('数字只能有一个小数点！')
            return False
    def to_int(self, int_arr) -> int:
        '''转整数'''
        number = 0
        for i in int_arr:
            number *= 10
            number += i
        return number

    def to_number(self) -> int|float:
        '''转数值'''
        dot_offset = self.e - self.dot
        if dot_offset < 0:  # 小数
            # 小数的如果转为float必然存在误差，只能用Decimal
            from decimal import Decimal
            number = Decimal((0, self.val, dot_offset))
        elif dot_offset == 0:  # 整数
            number = self.to_int(self.val)
        else: # 大数
            number = self.to_int(self.val)
            number *= 10**dot_offset
        if self.sign:
            return number
        else:
            return -1*number

    def to_str(self) -> str:
        ''' 转字符串'''
        StrNum = type(self)()
        StrNum.sign = self.sign
        StrNum.val  = self.val
        StrNum.dot  = self.dot
        str1 = str(StrNum.to_number())
        if self.e:
            str2 = str(self.e)
            return str1+'e'+str2
        else:
            return str1

    
if __name__ == '__main__':
    number_str = ['-435.032444e52', '-98', 0.0000000000002,
                  0.98E7, 32e-2, 0.21e+2, '-0.32E2', '32E-13',
                  '0.0000000000012', '0.1100000000000e5']
    for sn in number_str:
        print('source:', sn)
        sn = StrNumber(sn)
        print('number:', sn.to_number())
        print('string:', sn.to_str())
        print('-'*10)